#include <gtest/gtest.h>
#include "base/Thread.h"
#include <atomic>
#include <chrono>
#include <string>

using namespace cytoolkit;

// 测试构造函数和基本属性
TEST(ThreadTest, Constructor) {
    bool executed = false;
    Thread thread([&executed]() {
        executed = true;
    }, "TestThread");
    
    EXPECT_FALSE(thread.started());
    EXPECT_FALSE(thread.joinable());
    EXPECT_EQ(thread.name(), "TestThread");
    EXPECT_GT(Thread::numCreated(), 0);
}

// 测试线程启动和执行
TEST(ThreadTest, StartAndExecute) {
    bool executed = false;
    std::string threadName = "ExecuteThread";
    Thread thread([&executed]() {
        executed = true;
    }, threadName);
    
    thread.start();
    EXPECT_TRUE(thread.started());
    EXPECT_TRUE(thread.joinable());
    EXPECT_TRUE(thread.join());
    
    EXPECT_TRUE(executed);
}

// 测试线程join功能
TEST(ThreadTest, Join) {
    std::atomic<int> counter(0);
    Thread thread([&counter]() {
        Thread::msleep(100);
        counter = 42;
    });
    
    thread.start();
    EXPECT_TRUE(thread.join());
    EXPECT_FALSE(thread.joinable());
    EXPECT_EQ(counter, 42);
}

// 测试线程移动构造函数
TEST(ThreadTest, MoveConstructor) {
    bool executed = false;
    Thread thread1([&executed]() {
        executed = true;
        Thread::msleep(100);
    }, "Thread1");
    
    thread1.start();
    std::thread::id tid = thread1.tid();
    
    Thread thread2(std::move(thread1));
    EXPECT_FALSE(thread1.started());
    EXPECT_FALSE(thread1.joinable());
    EXPECT_TRUE(thread2.started());
    EXPECT_TRUE(thread2.joinable());
    EXPECT_EQ(thread2.tid(), tid);
    
    EXPECT_TRUE(thread2.join());
    EXPECT_TRUE(executed);
}

// 测试线程移动赋值运算符
TEST(ThreadTest, MoveAssignment) {
    bool executed1 = false;
    bool executed2 = false;
    
    Thread thread1([&executed1]() {
        executed1 = true;
    });
    
    Thread thread2([&executed2]() {
        executed2 = true;
        Thread::msleep(100);
    }, "Thread2");
    
    thread2.start();
    std::thread::id tid = thread2.tid();
    
    thread1 = std::move(thread2);
    EXPECT_FALSE(thread2.started());
    EXPECT_FALSE(thread2.joinable());
    EXPECT_TRUE(thread1.started());
    EXPECT_TRUE(thread1.joinable());
    EXPECT_EQ(thread1.tid(), tid);
    
    EXPECT_TRUE(thread1.join());
    EXPECT_TRUE(executed2);
    EXPECT_FALSE(executed1); // thread1原来的函数不应该执行
}

// 测试usleep静态方法
TEST(ThreadTest, Usleep) {
    auto start = std::chrono::steady_clock::now();
    Thread::usleep(5000); // 5毫秒
    auto end = std::chrono::steady_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
    
    // 允许一定的时间误差
    EXPECT_GE(duration, 4000); // 至少4毫秒
    EXPECT_LE(duration, 20000); // 最多20毫秒
}

// 测试msleep静态方法
TEST(ThreadTest, Msleep) {
    auto start = std::chrono::steady_clock::now();
    Thread::msleep(10); // 10毫秒
    auto end = std::chrono::steady_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
    
    // 允许一定的时间误差
    EXPECT_GE(duration, 5); // 至少5毫秒
    EXPECT_LE(duration, 30); // 最多30毫秒
}

// 测试threadID静态方法
TEST(ThreadTest, ThreadID) {
    int mainThreadId = Thread::threadID();
    EXPECT_GT(mainThreadId, 0);
    
    // 在另一个线程中获取ID
    std::atomic<int> threadId(0);
    Thread thread([&threadId]() {
        threadId = Thread::threadID();
        EXPECT_GT(threadId, 0);
    });
    
    thread.start();
    thread.join();
    
    // 主线程ID和新线程ID应该不同
    EXPECT_NE(mainThreadId, threadId);
}

// 测试setName静态方法
TEST(ThreadTest, SetName) {
    // 设置当前线程名称
    std::string testName = "GtestThread";
    Thread::setName(testName);
    
    // 这个测试主要是验证函数调用不会崩溃
    // 实际名称验证通常需要平台特定的API
    EXPECT_TRUE(true);
}

// 测试setAffinity静态方法
TEST(ThreadTest, SetAffinity) {
    // 尝试设置CPU亲和性到CPU 0
    bool result = Thread::setAffinity(0);
    
    // 在某些环境下可能不支持或没有权限设置亲和性
    // 所以不做严格的成功验证，只确保函数调用不会崩溃
    (void)result; // 避免未使用变量警告
    EXPECT_TRUE(true);
}

// 测试线程异常处理
TEST(ThreadTest, ExceptionHandling) {
    bool caughtException = false;
    Thread thread([&caughtException]() {
        try {
            throw std::runtime_error("Test exception");
        } catch (...) {
            caughtException = true;
            // 重新抛出以测试线程的异常处理
            throw;
        }
    });
    
    thread.start();
    thread.join();
    
    EXPECT_TRUE(caughtException);
}

// 测试线程重复启动
TEST(ThreadTest, DoubleStart) {
    int executeCount = 0;
    Thread thread([&executeCount]() {
        executeCount++;
    });
    
    thread.start();
    thread.start(); // 尝试再次启动
    thread.join();
    
    EXPECT_EQ(executeCount, 1); // 应该只执行一次
}

int main(int argc, char** argv) {
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}